package com.adam.example;

import com.vividsolutions.jts.geom.Coordinate;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.FuzzyQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.ExponentialDecayFunctionBuilder;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.percolator.PercolateQueryBuilder;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SearchExample {

    public static void main(String[] args) throws IOException {
        TransportClient transportClient = TransportClientHolder.getInstance().getTransportClient();

        //全文查询
//        QueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "python").operator(Operator.AND);
//        QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
//        QueryBuilder queryBuilder = QueryBuilders.matchPhraseQuery("title", "spring cloud");
//        QueryBuilder queryBuilder = QueryBuilders.matchPhrasePrefixQuery("title", "spring cl");
//        QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("java", "title", "description");
//        QueryBuilder queryBuilder = QueryBuilders.commonTermsQuery("title", "java and python")
//                .cutoffFrequency(0.3f).lowFreqOperator(Operator.OR).highFreqOperator(Operator.AND);
//        QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("+java -python").field("title", 1.2f)
//                .field("description");
//        QueryBuilder queryBuilder = QueryBuilders.simpleQueryStringQuery("|java -python |\"spring cloud\"")
//                .field("title", 1.2f).field("description");

        //词项查询
//        QueryBuilder queryBuilder = QueryBuilders.termQuery("title", "java");
//        QueryBuilder queryBuilder = QueryBuilders.termsQuery("title", "java", "python");
//        QueryBuilder queryBuilder = QueryBuilders.rangeQuery("price").gte(54.5).lte(80);
//        QueryBuilder queryBuilder = QueryBuilders.rangeQuery("publish_time").format("yyyy-MM-dd")
//                .gte("2014-01-01").lte("2014-12-31");
//        QueryBuilder queryBuilder = QueryBuilders.existsQuery("language");
//        QueryBuilder queryBuilder = QueryBuilders.prefixQuery("title", "jav");
//        QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("author", "张若?");
//        QueryBuilder queryBuilder = QueryBuilders.regexpQuery("author", "Br.*");
//        QueryBuilder queryBuilder = QueryBuilders.fuzzyQuery("title", "javascritp")
//                .fuzziness(Fuzziness.build(2));
//        QueryBuilder queryBuilder = QueryBuilders.typeQuery("IT");
//        QueryBuilder queryBuilder = QueryBuilders.idsQuery("IT").addIds("1","3","5");

        //复合查询
//        QueryBuilder queryBuilder = QueryBuilders.constantScoreQuery(
//                QueryBuilders.termQuery("title", "java")).boost(1.2f);
//        QueryBuilder queryBuilder = QueryBuilders.disMaxQuery()
//                .add(QueryBuilders.matchQuery("title", "java"))
//                .add(QueryBuilders.matchQuery("title", "python"))
//                .tieBreaker(0.7f);
//        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
//                .must(QueryBuilders.matchQuery("title", "java"))
//                .mustNot(QueryBuilders.matchQuery("title", "python"))
//                .should(QueryBuilders.rangeQuery("price").gt(50).lt(80));
//        QueryBuilder queryBuilder = QueryBuilders.indicesQuery(QueryBuilders.matchQuery("title", "javascript"),
//                "test_books").noMatchQuery(QueryBuilders.matchQuery("title", "python"));
//        FunctionScoreQueryBuilder queryBuilder = QueryBuilders.functionScoreQuery(QueryBuilders.matchQuery("title", "java")
//                , ScoreFunctionBuilders.exponentialDecayFunction("price", 0, 1));  //0:origin原点 1:scale衰减常数 distance=与原点距离 评分类似于e^(-scale*distance)
//        BytesReference bytesReference = queryBuilder.buildAsBytes();  //转化成json
//        System.out.println(bytesReference.utf8ToString());
//        QueryBuilder queryBuilder = QueryBuilders.boostingQuery(QueryBuilders.matchQuery("title", "python"),
//                QueryBuilders.rangeQuery("publish_time").lte("2015-01-01")).negativeBoost(0.2f);
//        QueryBuilder queryBuilder = QueryBuilders.nestedQuery("users", QueryBuilders.boolQuery()
//                .must(QueryBuilders.matchQuery("users.first", "alice"))
//                .must(QueryBuilders.matchQuery("users.last", "white"))
//                , ScoreMode.Avg);
//        QueryBuilder queryBuilder = QueryBuilders.hasChildQuery("employee", QueryBuilders.rangeQuery("dob")
//                .gte("1980-01-01"), ScoreMode.Avg);
//        QueryBuilder queryBuilder = QueryBuilders.hasParentQuery("branch", QueryBuilders.matchQuery("country", "UK"), true);

        //位置查询
//        QueryBuilder queryBuilder = QueryBuilders.geoDistanceQuery("location")
//                .point(39.0851000000, 117.1993700000).distance(200, DistanceUnit.KILOMETERS);
//        QueryBuilder queryBuilder = QueryBuilders.geoBoundingBoxQuery("location")
//                .setCorners(38.4864400000, 106.2324800000, 28.6820200000, 117.1993700000);
//        QueryBuilder queryBuilder = QueryBuilders.geoPolygonQuery("location", Arrays.asList(
//                new GeoPoint(40.8414900000, 111.7519900000), new GeoPoint(29.5647100000, 106.5507300000),
//                new GeoPoint(31.2303700000, 121.4737000000)));
//        QueryBuilder queryBuilder = QueryBuilders.geoShapeQuery("shape_location", ShapeBuilders.newEnvelope(
//                new Coordinate(106.23248, 38.48644), new Coordinate(115.85794, 28.68202)
//        )).relation(ShapeRelation.WITHIN);

        //特殊查询
//        QueryBuilder queryBuilder = QueryBuilders.moreLikeThisQuery(new String[]{"title", "description"}, new String[]{"python"}, null)
//                .minTermFreq(1).minDocFreq(1);
//        QueryBuilder queryBuilder = QueryBuilders.scriptQuery(new Script("doc['price'].value > 80"));
        XContentBuilder docBuilder = XContentFactory.jsonBuilder()
                .startObject()
                .field("price", 9999)
                .field("name", "macbook pro")
                .endObject();
        QueryBuilder queryBuilder = new PercolateQueryBuilder("query", "laptop", docBuilder.bytes(), XContentType.JSON);
        HighlightBuilder highlightBuilder = new HighlightBuilder()
                .requireFieldMatch(false)
                .field("title")
                .preTags("<span style=\"color:red\">")
                .postTags("</span>")
                .field("description")
                .preTags("<span style=\"color:red\">")
                .postTags("</span>");
        SearchResponse searchResponse = transportClient.prepareSearch(
//                "test_books"
//                "test"
//                "test_company"
                "test_percolate"
                ).setQuery(queryBuilder)
                .highlighter(highlightBuilder)
                .setSize(100)
                .get();
        SearchHits searchHits = searchResponse.getHits();
        SearchHit[] searchHitsArray = searchHits.getHits();
        for(int i=0;i< searchHitsArray.length; i++) {
            SearchHit searchHit = searchHitsArray[i];
            System.out.println("获取文档[" + (i+1) + "][评分" + searchHit.getScore() + "]:" + searchHit.getSourceAsString());
            HighlightField highlightFieldTitle = searchHit.getHighlightFields().get("title"),
                    highlightFieldDescription = searchHit.getHighlightFields().get("description");
            if(highlightFieldTitle != null) {
                Text[] highlightTextsTitle = highlightFieldTitle.getFragments();
                List<String> highlightStringsTitle = Arrays.stream(highlightTextsTitle).map(Text::string).collect(Collectors.toList());
                System.out.println("title高亮文本：" + highlightStringsTitle);
            }
            if(highlightFieldDescription != null) {
                Text[] highlightTextsDescription = searchHit.getHighlightFields().get("description").getFragments();
                List<String> highlightStringsDescription = Arrays.stream(highlightTextsDescription).map(Text::string).collect(Collectors.toList());
                System.out.println("description高亮文本：" + highlightStringsDescription);
            }
        }

        docBuilder.close();
        transportClient.close();
    }

}
